home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Sample Code / AppsToGo / DTS.Draw / TPieObj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  14.1 KB  |  528 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        TPieObj.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1992-1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /* See the files "=How to write your app" and "=Using TreeObj.c" for information
  20. ** on this function. */
  21.  
  22. /* This file implements the messages for the pie object.  Many of the messages
  23. ** can be handled by the rect object, as they deal with a rect structure.  Only
  24. ** a few of them are pie-specific. */
  25.  
  26. /* We have a custom hit-test handler here because there are additional sizing
  27. ** grabbers for the pie object.  The other objects just have grabbers at the
  28. ** corners.  A pie object also has grabber objects to adjust the "pie-slice". */
  29.  
  30.  
  31.  
  32. /*****************************************************************************/
  33.  
  34.  
  35.  
  36. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  37. #include "App.protos.h"        /* Get the prototypes for the application.        */
  38.  
  39. #ifndef __OSEVENTS__
  40. #include <OSEvents.h>
  41. #endif
  42.  
  43. #ifndef __OSUTILS__
  44. #include <OSUtils.h>
  45. #endif
  46.  
  47. #ifndef __QUICKDRAW__
  48. #include <Quickdraw.h>
  49. #endif
  50.  
  51. #ifndef __STRING__
  52. #include <String.h>
  53. #endif
  54.  
  55. #ifndef __TREEOBJ2__
  56. #include "TreeObj2.h"
  57. #endif
  58.  
  59. #ifndef __UTILITIES__
  60. #include "Utilities.h"
  61. #endif
  62.  
  63.  
  64.  
  65. static OSErr    PieLayerProc(LayerObj theLayer, short message);
  66.  
  67.  
  68.  
  69. /*****************************************************************************/
  70.  
  71.  
  72.  
  73. #pragma segment DrawObjects
  74. long    TPieObj(TreeObjHndl hndl, short message, long data)
  75. {
  76.     ClickInfo    *click;
  77.     Rect        rct;
  78.     TreeObjHndl    hhndl;
  79.     RgnHandle    rgn, oldClip, newClip, accumRgn;
  80.     short        arcs, arcl, arcs2, arcl2, diff, i, angle, h, w;
  81.     Point        pt, where, curMouse;
  82.     long        flip, newSize;
  83.     LayerObj    pieLayer;
  84.     EventRecord    option;
  85.     RGBColor    rgb, rgb2;
  86. #if VH_VERSION
  87.     char        *cptr;
  88. #endif
  89.  
  90.     switch (message) {
  91.         case INITMESSAGE:
  92.             TRectObj(hndl, message, data);
  93.             mDerefPie(hndl)->arcStart  = 0;
  94.             mDerefPie(hndl)->arcLength = 360;
  95.             break;
  96.  
  97.         case FREEMESSAGE:
  98.         case COPYMESSAGE:
  99.         case UNDOMESSAGE:
  100.         case CONVERTMESSAGE:
  101.         case FREADMESSAGE:
  102.         case FWRITEMESSAGE:
  103.         case HREADMESSAGE:
  104.         case HWRITEMESSAGE:
  105.         case GETOBJRECTMESSAGE:
  106.         case SECTOBJRECTMESSAGE:
  107.         case KEYMESSAGE:
  108.         case SETSELECTMESSAGE:
  109.         case GETSELECTMESSAGE:
  110.         case COMPAREMESSAGE:
  111.             return(TRectObj(hndl, message, data));
  112.             break;
  113.  
  114.         case GETBBOXMESSAGE:
  115.             return(TLineObj(hndl, message, data));
  116.             break;
  117.  
  118.         case HITTESTMESSAGE:
  119.             click = (ClickInfo *)data;
  120.             hhndl = (TreeObjHndl)TRectObj(hndl, message, data);
  121.                 /* We must call TRectObj::HITTESTMESSAGE to set some static
  122.                 ** variables that TRectObj::SELECTOBJMESSAGE uses. */
  123.             if ((!hhndl) && (click->message == HITTESTGRABBER)) {
  124.                 if (mDerefRoot(GetRootHndl(hndl))->numSelected == 1) {
  125.                     if (mDerefPie(hndl)->selected) {
  126.                         rct   = mDerefPie(hndl)->arc;
  127.                         where = click->localEvent.where;
  128.                         InsetRect(&rct, -4, -4);
  129.                         if (PtInRect(where, &rct)) {
  130.                             GetMouse(&curMouse);
  131.                             for (i = 0; i < 2; ++i) {
  132.                                 pt = (i) ? mDerefPie(hndl)->arcEnd : mDerefPie(hndl)->arcBegin;
  133.                                 rct.bottom = (rct.top  = pt.v - 3) + 6;
  134.                                 rct.right  = (rct.left = pt.h - 3) + 6;
  135.                                 if (PtInRect(where, &rct)) {
  136.                                     click->localEvent.where = pt;
  137.                                     click->offset.h         = pt.h - curMouse.h;
  138.                                     click->offset.v         = pt.v - curMouse.v;
  139.                                     click->oldFlip          = 0;
  140.                                     click->newFlip          = 0;
  141.                                     click->grabber          = 5 + i;
  142.                                     hhndl = hndl;
  143.                                     break;
  144.                                 }
  145.                             }
  146.                         }
  147.                     }
  148.                 }
  149.             }
  150.             return((long)hhndl);
  151.             break;
  152.  
  153.         case GETRGNMESSAGE:
  154.             rgn      = NewRgn();
  155.             accumRgn = (RgnHandle)data;
  156.             if (accumRgn)
  157.                 if (GetHandleSize((Handle)accumRgn) > 10000)
  158.                     return((long)rgn);
  159.             NewLayer(&pieLayer, nil, PieLayerProc, nil, 0, (long)hndl);
  160.             if (pieLayer) {
  161.                 SetLayerWorld(pieLayer);
  162.                 TPieObj(hndl, DRAWMESSAGE, DRAWMASK);
  163.                 BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  164.                 ResetLayerWorld(pieLayer);
  165.                 DisposeLayer(pieLayer);
  166.             }
  167.             if (accumRgn)
  168.                 UnionRgn(rgn, accumRgn, accumRgn);
  169.             return((long)rgn);
  170.             break;
  171.  
  172.         case SETOBJRECTMESSAGE:
  173.             TRectObj(hndl, message, data);
  174.             CalcPiePoints(hndl);
  175.             break;
  176.  
  177.         case DRAWMESSAGE:
  178.             rct = mDerefPie(hndl)->arc;
  179.             h   = mDerefCommon(hndl)->penHeight;
  180.             w   = mDerefCommon(hndl)->penWidth;
  181.             PenSize(w, h);
  182.             if (!EmptyRect(&rct)) {
  183.                 arcs = mDerefPie(hndl)->arcStart;
  184.                 arcl = mDerefPie(hndl)->arcLength;
  185.                 switch (data) {
  186.                     case DRAWOBJ:
  187.                         GetClip(oldClip = NewRgn());
  188.                         newClip = (RgnHandle)TOvalObj(hndl, GETRGNMESSAGE, 0);
  189.                         if (newClip)
  190.                             SetClip(newClip);
  191.                         if (gQDVersion)
  192.                             GetForeColor(&rgb);
  193.                         ForeColor(whiteColor);
  194.                         if (gQDVersion) {
  195.                             rgb2 = mDerefPie(hndl)->contentColor;
  196.                             RGBForeColor(&rgb2);
  197.                         }
  198.                         PaintArc(&rct, arcs, arcl);
  199.                         ForeColor(blackColor);
  200.                         if (gQDVersion) {
  201.                             rgb2 = mDerefPie(hndl)->borderColor;
  202.                             RGBForeColor(&rgb2);
  203.                         }
  204.                         FrameArc(&rct, arcs, arcl);
  205.                         pt = mDerefPie(hndl)->arcBegin;
  206.                         MoveTo(pt.h - (w / 2), pt.v - (w / 2));
  207.                         pt = mDerefPie(hndl)->center;
  208.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  209.                         pt = mDerefPie(hndl)->arcEnd;
  210.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  211.                         if (gQDVersion)
  212.                             RGBForeColor(&rgb);
  213.                         SetClip(oldClip);
  214.                         DisposeRgn(oldClip);
  215.                         if (newClip)
  216.                             DisposeRgn(newClip);
  217.                         break;
  218.                     case ERASEOBJ:
  219.                         EraseArc(&rct, arcs, arcl);
  220.                         break;
  221.                     case DRAWSELECT:
  222.                         if (mDerefPie(hndl)->selected) {
  223.                             TRectObj(hndl, message, data);
  224.                             for (i = 0; i < 2; ++i) {
  225.                                 pt = (i) ? mDerefPie(hndl)->arcEnd : mDerefPie(hndl)->arcBegin;
  226.                                 rct.bottom = (rct.top  = pt.v - 3) + 6;
  227.                                 rct.right  = (rct.left = pt.h - 3) + 6;
  228.                                 InvertRect(&rct);
  229.                                 arcl = mDerefPie(hndl)->arcLength;
  230.                                 if ((arcl == -360) || (!arcl) || (arcl == 360)) break;
  231.                             }
  232.                         }
  233.                         break;
  234.                     case DRAWGHOST:
  235.                         PenMode(patXor);
  236.                         FrameArc(&rct, arcs, arcl);
  237.                         break;
  238.                     case DRAWMASK:
  239.                         FillArc(&rct, arcs, arcl, (ConstPatternParam)&qd.black);
  240.                         FrameArc(&rct, arcs, arcl);
  241.                         pt = mDerefPie(hndl)->arcBegin;
  242.                         MoveTo(pt.h - (w / 2), pt.v - (w / 2));
  243.                         pt = mDerefPie(hndl)->center;
  244.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  245.                         pt = mDerefPie(hndl)->arcEnd;
  246.                         LineTo(pt.h - (w / 2), pt.v - (w / 2));
  247.                         break;
  248.                 }
  249.             }
  250.             PenNormal();
  251.             break;
  252.  
  253.         case PRINTMESSAGE:
  254.             TPieObj(hndl, DRAWMESSAGE, DRAWOBJ);
  255.             break;
  256.  
  257. #if VH_VERSION
  258.         case VHMESSAGE:
  259.             cptr = ((VHFormatDataPtr)data)->data;
  260.             ccatchr(cptr, 13, 2);
  261.             ccat   (cptr, "$10: TPieObj:");
  262.             ccatchr(cptr, 13, 1);
  263.             ccat   (cptr, "  $00: selected = ");
  264.             ccatdec(cptr, mDerefPie(hndl)->selected);
  265.             ccatchr(cptr, 13, 1);
  266.             rct = mDerefPie(hndl)->arc;
  267.             ccat   (cptr, "  $02: pie      = (");
  268.             ccatdec(cptr, rct.top);
  269.             ccat   (cptr, ",");
  270.             ccatdec(cptr, rct.left);
  271.             ccat   (cptr, ",");
  272.             ccatdec(cptr, rct.bottom);
  273.             ccat   (cptr, ",");
  274.             ccatdec(cptr, rct.right);
  275.             ccat   (cptr, ")");
  276.             ccatchr(cptr, 13, 1);
  277.             ccat   (cptr, "  $0A: arcStart  = ");
  278.             ccatdec(cptr, mDerefPie(hndl)->arcStart);
  279.             ccatchr(cptr, 13, 1);
  280.             ccat   (cptr, "  $0C: arcLength = ");
  281.             ccatdec(cptr, mDerefPie(hndl)->arcLength);
  282.             ccatchr(cptr, 13, 1);
  283.             ccat   (cptr, "  $0E: center    = (");
  284.             ccatdec(cptr, mDerefPie(hndl)->center.v);
  285.             ccat   (cptr, ",");
  286.             ccatdec(cptr, mDerefPie(hndl)->center.h);
  287.             ccat   (cptr, ")");
  288.             ccatchr(cptr, 13, 1);
  289.             ccat   (cptr, "  $12: arcBegin  = (");
  290.             ccatdec(cptr, mDerefPie(hndl)->arcBegin.v);
  291.             ccat   (cptr, ",");
  292.             ccatdec(cptr, mDerefPie(hndl)->arcBegin.h);
  293.             ccat   (cptr, ")");
  294.             ccatchr(cptr, 13, 1);
  295.             ccat   (cptr, "  $16: arcEnd    = (");
  296.             ccatdec(cptr, mDerefPie(hndl)->arcEnd.v);
  297.             ccat   (cptr, ",");
  298.             ccatdec(cptr, mDerefPie(hndl)->arcEnd.h);
  299.             ccat   (cptr, ")");
  300.             ccatchr(cptr, 13, 1);
  301.             return(true);
  302.             break;
  303. #endif
  304.  
  305.         case CLICKMESSAGE:
  306.             TRectObj(hndl, message, data);
  307.             click = (ClickInfo *)data;
  308.             if (click->message == CLICKDRAG) {
  309.                 AddPt(click->offset, &mDerefPie(hndl)->center);
  310.                 AddPt(click->offset, &mDerefPie(hndl)->arcBegin);
  311.                 AddPt(click->offset, &mDerefPie(hndl)->arcEnd);
  312.             }
  313.             break;
  314.  
  315.         case SIZEMESSAGE:
  316.             click = (ClickInfo *)data;
  317.             if (click->grabber <= 4) {
  318.                 newSize = TRectObj(hndl, message, data);
  319.                 click = (ClickInfo *)data;
  320.                 flip = (click->oldFlip ^ click->newFlip);
  321.                 if (flip) {
  322.                     arcs = mDerefPie(hndl)->arcStart;
  323.                     arcl = mDerefPie(hndl)->arcLength;
  324.                     if (flip & VFLIPOBJ) {
  325.                         arcs -= (i = (arcs < 180) ? 0 : 180);
  326.                         arcs = 180 - arcs;
  327.                         arcl = -arcl;
  328.                         arcs += i;
  329.                     }
  330.                     if (flip & HFLIPOBJ) {
  331.                         arcs = 360 - arcs;
  332.                         arcl = -arcl;
  333.                     }
  334.                     mDerefPie(hndl)->arcStart  = arcs;
  335.                     mDerefPie(hndl)->arcLength = arcl;
  336.                 }
  337.                 CalcPiePoints(hndl);
  338.                 return(newSize);
  339.             }
  340.  
  341.             GetMouse(&curMouse);
  342.             curMouse.h += click->offset.h;
  343.             curMouse.v += click->offset.v;
  344.             rct = mDerefPie(hndl)->arc;
  345.  
  346.             arcs = arcs2 = mDerefPie(hndl)->arcStart;
  347.             arcl = arcl2 = mDerefPie(hndl)->arcLength;
  348.  
  349.             PtToAngle(&rct, curMouse, &angle);
  350.  
  351.             if (click->grabber == 6) {        /* Handle 2nd grabber as reverse first grabber case. */
  352.                 click->grabber = 5;
  353.                 arcs += arcl;
  354.                 arcl  = -arcl;
  355.                 while (arcs >  360) arcs -= 360;
  356.                 while (arcs <    0) arcs += 360;
  357.             }
  358.  
  359.             diff = angle - arcs;
  360.             arcs = angle;
  361.             OSEventAvail(nullEvent, &option);
  362.             if (!(option.modifiers & shiftKey)) {
  363.                 while (diff >  180) diff -= 360;        /* Force 1 change to be less than 180. */
  364.                 while (diff < -180) diff += 360;
  365.                 arcl   -= diff;
  366.                 while (arcl >  360) arcl -= 360;
  367.                 while (arcl < -360) arcl += 360;
  368.             }
  369.  
  370.             if ((arcs != arcs2) || (arcl != arcl2)) {
  371.                 mDerefPie(hndl)->arcStart  = arcs;
  372.                 mDerefPie(hndl)->arcLength = arcl;
  373.                 CalcPiePoints(hndl);
  374.                 return(true);
  375.             }
  376.             break;
  377.  
  378.         default:
  379.             break;
  380.     }
  381.  
  382.     return(noErr);
  383. }
  384.  
  385.  
  386.  
  387. /*****************************************************************************/
  388.  
  389.  
  390.  
  391. #pragma segment DrawObjects
  392. OSErr    CalcPiePoints(TreeObjHndl hndl)
  393. {
  394.     OSErr        err;
  395.     Rect        rct;
  396.     short        arcs, arcl, i, angle;
  397.     RgnHandle    rgn;
  398.     Point        pt;
  399.     long        ll;
  400.     LayerObj    pieLayer;
  401.  
  402.     err = NewLayer(&pieLayer, nil, PieLayerProc, nil, 0, (long)hndl);
  403.     if (err) return(err);
  404.  
  405.     rct  = mDerefPie(hndl)->arc;
  406.     arcs = mDerefPie(hndl)->arcStart;
  407.     arcl = mDerefPie(hndl)->arcLength;
  408.  
  409.     SetLayerWorld(pieLayer);
  410.     rgn = NewRgn();
  411.  
  412.     EraseRect(&rct);
  413.     FillArc(&rct, 90, 90, (ConstPatternParam)&qd.black);
  414.  
  415.     BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  416.     pt = *(Point *)(&(*rgn)->rgnBBox);
  417.     ll = PinRect(&rct, pt);
  418.     pt = *(Point *)≪
  419.     mDerefPie(hndl)->center = pt;
  420.  
  421.     for (i = 0; i < 2; ++i) {
  422.         angle = (i) ? (arcs + arcl) : (arcs);
  423.         while (angle < 0)    angle += 360;
  424.         while (angle >= 360) angle -= 360;
  425.         EraseRect(&rct);
  426.         if (angle < 90) {
  427.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  428.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  429.             pt.v = (*rgn)->rgnBBox.top;
  430.             EraseRect(&rct);
  431.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  432.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  433.             pt.h = (*rgn)->rgnBBox.right;
  434.             if (angle > 45)
  435.                 --pt.h;
  436.         }
  437.         if ((angle >= 90) && (angle < 180)) {
  438.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  439.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  440.             pt.h = (*rgn)->rgnBBox.right;
  441.             EraseRect(&rct);
  442.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  443.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  444.             pt.v = (*rgn)->rgnBBox.bottom;
  445.             if (angle < 135)
  446.                 --pt.h;
  447.             else
  448.                 --pt.v;
  449.         }
  450.         if ((angle >= 180) && (angle < 270)) {
  451.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  452.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  453.             pt.v = (*rgn)->rgnBBox.bottom;
  454.             EraseRect(&rct);
  455.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  456.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  457.             pt.h = (*rgn)->rgnBBox.left;
  458.             if (angle < 225)
  459.                 --pt.v;
  460.         }
  461.         if (angle >= 270) {
  462.             FillArc(&rct, angle, 90, (ConstPatternParam)&qd.black);
  463.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  464.             pt.h = (*rgn)->rgnBBox.left;
  465.             EraseRect(&rct);
  466.             FillArc(&rct, angle, -90, (ConstPatternParam)&qd.black);
  467.             BitMapToRegion(rgn, (BitMapPtr)(*((CGrafPtr)(*pieLayer)->layerPort)->portPixMap));
  468.             pt.v = (*rgn)->rgnBBox.top;
  469.         }
  470.         ll = PinRect(&rct, pt);
  471.         pt = *(Point *)≪
  472.         (i) ? (mDerefPie(hndl)->arcEnd = pt) : (mDerefPie(hndl)->arcBegin = pt);
  473.     }
  474.  
  475.     DisposeRgn(rgn);
  476.     ResetLayerWorld(pieLayer);
  477.     DisposeLayer(pieLayer);
  478.     return(noErr);
  479. }
  480.  
  481.  
  482.  
  483. /*****************************************************************************/
  484.  
  485.  
  486.  
  487. static OSErr    PieLayerProc(LayerObj theLayer, short message)
  488. {
  489.     OSErr        err;
  490.     TreeObjHndl    pie;
  491.     Rect        rct;
  492.     CGrafPtr    keepPort;
  493.     GDHandle    keepGDevice;
  494.     GWorldPtr    layerWorld;
  495.  
  496.     switch (message) {
  497.         case kLayerInit:
  498.             err = noErr;
  499.             if (theLayer) {
  500.                 if (!(*theLayer)->layerPort) {
  501.                     pie = (TreeObjHndl)(*theLayer)->layerData;
  502.                     rct = mDerefPie(pie)->arc;
  503.                     GetGWorld(&keepPort, &keepGDevice);        /* Keep the GWorld. */
  504.                     err = NewGWorld(&layerWorld, 1, &rct, nil, nil, 0);
  505.                     if (err == noErr) {
  506.                         (*theLayer)->layerOwnsPort = true;
  507.                         SetPort((*theLayer)->layerPort = (GrafPtr)layerWorld);
  508.                         SetOrigin(rct.left, rct.top);
  509.                         EraseRect(&rct);
  510.                     }
  511.                     SetGWorld(keepPort, keepGDevice);        /* Restore the kept GWorld. */
  512.                 }
  513.             }
  514.             else err = paramErr;
  515.             break;
  516.  
  517.         default:
  518.             err = DefaultLayerProc(theLayer, message);
  519.                 /* Default behavior for everything else. */
  520.             break;
  521.     }
  522.  
  523.     return(err);
  524. }
  525.  
  526.  
  527.  
  528.